﻿#include "EditorReflectedPropertyViewModel.h"

#include "Property/ReflectedProperty/EditorReflectedPropertyModel.h"

#include "Material/Material.h"
#include "Mesh/StaticMesh.h"
#include "Asset/EditorDefaultPackage.h"

#include "Window/EditorWindowGroupModel.h"
#include "Reflection/PropertyList.h"


static TWeakObjectPtr<REditorReflectedPropertyViewModel> GViewModel=nullptr;

void REditorReflectedPropertyViewModel::BindModel(TSharedObjectPtr<REditorPropertyModel> InModel, TSharedObjectPtr<REditorObjectPropertyAbilityViewModel> InAbilityViewModel)
{
    GViewModel=this;

    Super::BindModel(InModel, InAbilityViewModel);
    PropertyModel=InModel;

    ExpandedIcon = REditorDefaultPackage::Get()->GetIcon(U"CodiconChevronDown");
    CollapsedIcon = REditorDefaultPackage::Get()->GetIcon(U"CodiconChevronRight");


    UpdatePropertyNodes();
}

float REditorReflectedPropertyViewModel::GetListHeight() const
{
    return ListHeight;
}

int64_t REditorReflectedPropertyViewModel::GetLineItemNum() const
{
    return PropertyNodes.Num();
}

REditorReflectedPropertyViewModel::EPropertyType REditorReflectedPropertyViewModel::GetViewType(int64_t InIndex) const
{
    return PropertyNodes[InIndex]->ViewType;
}

float REditorReflectedPropertyViewModel::GetLineHeight(int64_t InIndex) const
{
    switch(PropertyNodes[InIndex]->ViewType)
    {
        case EPropertyType::StaticMesh:
        case EPropertyType::Material:
        {
            return LineHeight*2;
        }
        default:
        {
            return LineHeight;
        }
    }
}

float REditorReflectedPropertyViewModel::GetDepth(int64_t InIndex) const
{
    return PropertyNodes[InIndex]->Depth*10;
}

CString REditorReflectedPropertyViewModel::GetPropertyName(int64_t InIndex) const
{
    return PropertyNodes[InIndex]->DisplayName;
}

int64_t REditorReflectedPropertyViewModel::GetIntValue(int64_t InIndex) const
{
    if(PropertyNodes[InIndex]->Value)
    {
        //字段属性
        return *(int64_t*)PropertyNodes[InIndex]->Value;
    }
    else
    {
        //虚拟属性
        return AnyCast<int64_t>(PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get()));
    }

}

void REditorReflectedPropertyViewModel::SetIntValue(int64_t InIndex, int64_t InValue)
{
    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    if(PropertyNodes[InIndex]->Value)
    {
        //字段属性
        Operation->ChangeValue(
            PropertyModel->Object
            ,PropertyNodes[InIndex]->PropertyPath
            ,CAny(*(int64_t*)PropertyNodes[InIndex]->Value)
            ,CAny(InValue)
        );

    }
    else
    {
        //虚拟属性
        Operation->ChangeVirtualPropertyValue(
            PropertyNodes[InIndex]->PropertyOwner
            ,PropertyNodes[InIndex]->Property
            ,PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get())
            ,InValue
        );

    }
    Page->AddAndRedoOperation(Operation);
}

float REditorReflectedPropertyViewModel::GetFloatValue(int64_t InIndex) const
{
    if(PropertyNodes[InIndex]->Value)
    {
        //字段属性
        return *(float*)PropertyNodes[InIndex]->Value;
    }
    else
    {
        //虚拟属性
        return AnyCast<float>(PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get()));
    }
}

void REditorReflectedPropertyViewModel::SetFloatValue(int64_t InIndex, float InValue)
{
    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    if(PropertyNodes[InIndex]->Value)
    {
        //字段属性
        Operation->ChangeValue(
            PropertyModel->Object
            ,PropertyNodes[InIndex]->PropertyPath
            ,CAny(*(float*)PropertyNodes[InIndex]->Value)
            ,CAny(InValue)
        );

    }
    else
    {
        //虚拟属性
        Operation->ChangeVirtualPropertyValue(
            PropertyNodes[InIndex]->PropertyOwner
            ,PropertyNodes[InIndex]->Property
            ,PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get())
            ,InValue
        );

    }
    Page->AddAndRedoOperation(Operation);
}

bool REditorReflectedPropertyViewModel::GetBoolValue(int64_t InIndex) const
{
    if(PropertyNodes[InIndex]->Value)
    {
        //字段属性
        return *(bool*)PropertyNodes[InIndex]->Value;
    }
    else
    {
        //虚拟属性
        return AnyCast<bool>(PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get()));
    }
}

void REditorReflectedPropertyViewModel::SetBoolValue(int64_t InIndex, bool InValue)
{
    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    if(PropertyNodes[InIndex]->Value)
    {
        //字段属性
        Operation->ChangeValue(
            PropertyModel->Object
            ,PropertyNodes[InIndex]->PropertyPath
            ,CAny(*(bool*)PropertyNodes[InIndex]->Value)
            ,CAny(InValue)
        );

    }
    else
    {
        //虚拟属性
        Operation->ChangeVirtualPropertyValue(
            PropertyNodes[InIndex]->PropertyOwner
            ,PropertyNodes[InIndex]->Property
            ,PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get())
            ,InValue
        );

    }
    Page->AddAndRedoOperation(Operation);
}

CString REditorReflectedPropertyViewModel::GetStringValue(int64_t InIndex) const
{
    if(PropertyNodes[InIndex]->Value)
    {
        //字段属性
        return *(CString*)PropertyNodes[InIndex]->Value;
    }
    else
    {
        //虚拟属性
        return AnyCast<CString>(PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get()));
    }
}

void REditorReflectedPropertyViewModel::SetStringValue(int64_t InIndex, CString InValue)
{
    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    if(PropertyNodes[InIndex]->Value)
    {
        //字段属性
        Operation->ChangeValue(
            PropertyModel->Object
            ,PropertyNodes[InIndex]->PropertyPath
            ,CAny(*(CString*)PropertyNodes[InIndex]->Value)
            ,CAny(InValue)
        );

    }
    else
    {
        //虚拟属性
        Operation->ChangeVirtualPropertyValue(
            PropertyNodes[InIndex]->PropertyOwner
            ,PropertyNodes[InIndex]->Property
            ,PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get())
            ,InValue
        );

    }
    Page->AddAndRedoOperation(Operation);
}

TSharedObjectPtr<RStaticMesh> REditorReflectedPropertyViewModel::GetStaticMeshValue(int64_t InIndex) const
{
    if(PropertyNodes[InIndex]->Value)
    {
        return *(TSharedObjectPtr<RStaticMesh>*)PropertyNodes[InIndex]->Value;
    }
    else
    {
        return AnyCast<TSharedObjectPtr<RStaticMesh>>(PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get()));
    }
}

void REditorReflectedPropertyViewModel::SetStaticMeshValue(int64_t InIndex, TSharedObjectPtr<RStaticMesh> InValue)
{
    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    if(PropertyNodes[InIndex]->Value)
    {
        Operation->ChangeValue(
            PropertyModel->Object
            ,PropertyNodes[InIndex]->PropertyPath
            ,CAny(*(TSharedObjectPtr<RStaticMesh>*)PropertyNodes[InIndex]->Value)
            ,CAny(InValue)
        );
    }
    else
    {
        Operation->ChangeVirtualPropertyValue(
            PropertyNodes[InIndex]->PropertyOwner
            ,PropertyNodes[InIndex]->Property
            ,PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get())
            ,InValue
        );
    }
    Page->AddAndRedoOperation(Operation);
}

TSharedObjectPtr<RMaterial> REditorReflectedPropertyViewModel::GetMaterialValue(int64_t InIndex) const
{
    if(PropertyNodes[InIndex]->Value)
    {
        return *(TSharedObjectPtr<RMaterial>*)PropertyNodes[InIndex]->Value;
    }
    else
    {
        return AnyCast<TSharedObjectPtr<RMaterial>>(PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get()));
    }
}

void REditorReflectedPropertyViewModel::SetMaterialValue(int64_t InIndex, TSharedObjectPtr<RMaterial> InValue)
{
    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    if(PropertyNodes[InIndex]->Value)
    {
        Operation->ChangeValue(
            PropertyModel->Object
            ,PropertyNodes[InIndex]->PropertyPath
            ,CAny(*(TSharedObjectPtr<RMaterial>*)PropertyNodes[InIndex]->Value)
            ,CAny(InValue)
        );
    }
    else
    {
        Operation->ChangeVirtualPropertyValue(
            PropertyNodes[InIndex]->PropertyOwner
            ,PropertyNodes[InIndex]->Property
            ,PropertyNodes[InIndex]->Property->NonStaticProperty->GetValue(PropertyNodes[InIndex]->PropertyOwner.Get())
            ,InValue
        );
    }
    Page->AddAndRedoOperation(Operation);
}

bool REditorReflectedPropertyViewModel::HasExpandIcon(int64_t InIndex) const
{
    return PropertyNodes[InIndex]->SubNodeNum>0;
}

TSharedObjectPtr<RTexture2D> REditorReflectedPropertyViewModel::GetExpandIcon(int64_t InIndex) const
{
    if(PropertyNodes[InIndex]->SubNodeNum>0)
    {
        if(PropertyNodes[InIndex]->bIsExpanded)
        {
            return ExpandedIcon;
        }
        else
        {
            return CollapsedIcon;
        }
    }
    return nullptr;

}

void REditorReflectedPropertyViewModel::ToggleExpand(int64_t InIndex)
{
    if(PropertyNodes[InIndex]->bIsExpanded)
    {
        ExendedPropertyValues.Remove(PropertyNodes[InIndex]->Value);
    }
    else
    {
        ExendedPropertyValues.Add(PropertyNodes[InIndex]->Value);
    }

    PropertyNodes[InIndex]->bIsExpanded=!PropertyNodes[InIndex]->bIsExpanded;

    UpdatePropertyNodes();
    OnListChanged.ExecuteIfBound();
}

int64_t REditorReflectedPropertyViewModel::GetSubNodeNum(int64_t InIndex) const
{
    return PropertyNodes[InIndex]->SubNodeNum;
}

bool REditorReflectedPropertyViewModel::HasMoreOperationButton(int64_t InIndex) const
{
    return PropertyNodes[InIndex]->OperationFlag!=EOperationFlag::None;
}

bool REditorReflectedPropertyViewModel::CanDelete(int64_t InIndex) const
{
    return ((uint64_t)PropertyNodes[InIndex]->OperationFlag & (uint64_t)EOperationFlag::Delete) != 0;
}

void REditorReflectedPropertyViewModel::Delete(int64_t InIndex)
{
    auto PropertyNode = PropertyNodes[InIndex];
    auto ParentNode=PropertyNode->Parent;

    assert(ParentNode && ParentNode->Type->IsVectorType());

    CAny NewValue=CAny::Clone(ParentNode->Type, ParentNode->Value);
    CReflectableVector* VectorBase=reinterpret_cast<CReflectableVector*>(NewValue.GetPointer());
    VectorBase->RemoveAt(PropertyNode->Type,PropertyNode->IndexInParent);

    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    Operation->ChangeValue(
        PropertyModel->Object
        ,ParentNode->PropertyPath
        ,CAny::Clone(ParentNode->Type, ParentNode->Value)
        ,std::move(NewValue)
    );

    Operation->OnUndoRedo.Bind([]()
    {   
        //use global variable
        //because when undo redo, the view model may be destroyed and recreated
        if(GViewModel)
        {
            GViewModel->UpdatePropertyNodes();
            GViewModel->OnListChanged.ExecuteIfBound();
        }
    });

    Page->AddAndRedoOperation(Operation);
}

bool REditorReflectedPropertyViewModel::CanInsert(int64_t InIndex) const
{
    return ((uint64_t)PropertyNodes[InIndex]->OperationFlag & (uint64_t)EOperationFlag::Insert) != 0;
}

void REditorReflectedPropertyViewModel::Insert(int64_t InIndex)
{
    auto PropertyNode = PropertyNodes[InIndex];
    auto ParentNode=PropertyNode->Parent;

    assert(ParentNode && ParentNode->Type->IsVectorType());

    CAny NewValue=CAny::Clone(ParentNode->Type, ParentNode->Value);
    CReflectableVector* VectorBase=reinterpret_cast<CReflectableVector*>(NewValue.GetPointer());
    VectorBase->InsertDefault(PropertyNode->Type,PropertyNode->IndexInParent);

    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    Operation->ChangeValue(
        PropertyModel->Object
        ,ParentNode->PropertyPath
        ,CAny::Clone(ParentNode->Type, ParentNode->Value)
        ,std::move(NewValue)
    );

    Operation->OnUndoRedo.Bind([]()
    {   
        //use global variable
        //because when undo redo, the view model may be destroyed and recreated
        if(GViewModel)
        {
            GViewModel->UpdatePropertyNodes();
            GViewModel->OnListChanged.ExecuteIfBound();
        }
    });

    Page->AddAndRedoOperation(Operation);
}

bool REditorReflectedPropertyViewModel::CanDuplicate(int64_t InIndex) const
{
    return ((uint64_t)PropertyNodes[InIndex]->OperationFlag & (uint64_t)EOperationFlag::Duplicate) !=  0;
}

void REditorReflectedPropertyViewModel::Duplicate(int64_t InIndex)
{
    auto PropertyNode = PropertyNodes[InIndex];
    auto ParentNode=PropertyNode->Parent;

    assert(ParentNode && ParentNode->Type->IsVectorType());

    CAny NewValue=CAny::Clone(ParentNode->Type, ParentNode->Value);
    CReflectableVector* VectorBase=reinterpret_cast<CReflectableVector*>(NewValue.GetPointer());
    VectorBase->Insert(PropertyNode->Type,PropertyNode->IndexInParent,PropertyNode->Value);

    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    Operation->ChangeValue(
        PropertyModel->Object
        ,ParentNode->PropertyPath
        ,CAny::Clone(ParentNode->Type, ParentNode->Value)
        ,std::move(NewValue)
    );

    Operation->OnUndoRedo.Bind([]()
    {   
        //use global variable
        //because when undo redo, the view model may be destroyed and recreated
        if(GViewModel)
        {
            GViewModel->UpdatePropertyNodes();
            GViewModel->OnListChanged.ExecuteIfBound();
        }
    });

    Page->AddAndRedoOperation(Operation);
}

void REditorReflectedPropertyViewModel::AddVectorItem(int64_t InIndex)
{
    auto PropertyNode = PropertyNodes[InIndex];
    if(PropertyNode->SubNodeNum==0)
    {
        return;
    }

    if(!PropertyNode->bIsExpanded)
    {
        PropertyNode->bIsExpanded=true;
        ExendedPropertyValues.Add(PropertyNode->Value);
    }

    //add item
    CTVectorGeneralized * VectorType
         = reinterpret_cast<CTVectorGeneralized*>(PropertyNode->Type);
    CType* ElementType = VectorType->GetElementType().BasicType;

    CAny NewValue=CAny::Clone(PropertyNode->Type, PropertyNode->Value);
    CReflectableVector* VectorBase=reinterpret_cast<CReflectableVector*>(NewValue.GetPointer());
    VectorBase->AddDefault(ElementType);

    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    Operation->ChangeValue(
        PropertyModel->Object
        ,PropertyNode->PropertyPath
        ,CAny::Clone(PropertyNode->Type, PropertyNode->Value)
        ,std::move(NewValue)
    );

    Operation->OnUndoRedo.Bind([]()
    {   
        //use global variable
        //because when undo redo, the view model may be destroyed and recreated
        if(GViewModel)
        {
            GViewModel->UpdatePropertyNodes();
            GViewModel->OnListChanged.ExecuteIfBound();
        }
    });

    Page->AddAndRedoOperation(Operation);

}

void REditorReflectedPropertyViewModel::ClearVector(int64_t InIndex)
{
    auto PropertyNode = PropertyNodes[InIndex];
    if(PropertyNode->SubNodeNum==0)
    {
        return;
    }

    if(PropertyNode->bIsExpanded)
    {
        PropertyNode->bIsExpanded=false;
        ExendedPropertyValues.Remove(PropertyNode->Value);
    }


    auto Page=REditorWindowGroupModel::Get()->GetFocusedPage();
    auto Operation= NewObject<REditorPropertyOperation>(Page);
    Operation->ChangeValue(
        PropertyModel->Object
        ,PropertyNode->PropertyPath
        ,CAny::Clone(PropertyNode->Type, PropertyNode->Value)
        ,CAny(PropertyNode->Type, PropertyNode->Type->CreateInstance()) //empty vector
    );

    Operation->OnUndoRedo.Bind([]()
    {   
        //use global variable
        //because when undo redo, the view model may be destroyed and recreated
        if(GViewModel)
        {
            GViewModel->UpdatePropertyNodes();
            GViewModel->OnListChanged.ExecuteIfBound();
        }
    });

    Page->AddAndRedoOperation(Operation);

}

void REditorReflectedPropertyViewModel::UpdatePropertyNodes()
{
    PropertyNodes.Clear();
   
    for (auto& Property : PropertyModel->Object->GetClass()->Properties->GetProperties())
    {
        if(Property->IsStatic())
        {
            continue;
        }

        CreateAndAddPropertyNode(
            Property
            ,PropertyModel->Object
            ,0
        );
    }


    //count height
    ListHeight=0;
    for (auto& Node : PropertyNodes)
    {
        switch(Node->ViewType)
        {
            case EPropertyType::StaticMesh:
            case EPropertyType::Material:
            {
                ListHeight+=LineHeight*2;
            }
            break;
            default:
            {
                ListHeight+=LineHeight;
            }
        }
    }
}

void REditorReflectedPropertyViewModel::CreateAndAddPropertyNode(CProperty *InProperty, RObjectPtr InOwner, int64_t InDepth)
{
    CType* PropertyType = InProperty->GetType().BasicType;

    if(InProperty->IsField())
    {
        void* PropertyValue = InProperty->FieldProperty->GetValuePointer(InOwner.Get());
        
        CreateAndAddPropertyNodeByValue(
            PropertyType
            , PropertyValue
            , InProperty->GetName() 
            , InProperty->GetName()
            , nullptr
            );
    }
    else
    {
        //虚拟属性
        EPropertyType Type = ToViewType(PropertyType);
        if(Type==EPropertyType::Invalid
            || PropertyType->IsVectorType()
            || PropertyType->IsMapType()
            || PropertyType->IsStructType()
        )
        {
            //not supported type
            return ;
        }

        auto PropertyNode = std::make_shared<SPropertyValue>();
        PropertyNode->Type = PropertyType;
        PropertyNode->Value = nullptr;
        PropertyNode->DisplayName = InProperty->GetName();
        PropertyNode->Depth = InDepth;
        PropertyNode->ViewType = Type;
        PropertyNode->PropertyPath.Add(InProperty->GetName());
        PropertyNode->Parent=nullptr;

        PropertyNode->PropertyOwner=InOwner;
        PropertyNode->Property=InProperty;

        PropertyNodes.Add(PropertyNode);
    }


}

std::shared_ptr<REditorReflectedPropertyViewModel::SPropertyValue> REditorReflectedPropertyViewModel::CreateAndAddPropertyNodeByValue(
    CType *InType
    , void *InValue
    , const CString& InDisplayName
    , const CString & InPropertyName
    , std::shared_ptr<SPropertyValue> InParent
    )
{
    //get view type
    EPropertyType Type = ToViewType(InType);
    if(Type==EPropertyType::Invalid)
    {
        //not supported type
        return nullptr;
    }


    auto PropertyNode = std::make_shared<SPropertyValue>();
    PropertyNode->Type = InType;
    PropertyNode->Value = InValue;
    PropertyNode->DisplayName = InDisplayName;
    if(InParent)
    {
        PropertyNode->Depth = InParent->Depth+1;
    }
    else
    {
        PropertyNode->Depth = 0;
    }

    PropertyNode->ViewType = Type;

    if(InParent)
    {
        PropertyNode->PropertyPath=InParent->PropertyPath;
    }
    PropertyNode->PropertyPath.Add(InPropertyName);

    if(InParent)
    {
        PropertyNode->Parent=InParent;

        if(InParent->Type->IsVectorType())
        {
            PropertyNode->OperationFlag=EOperationFlag(
                (uint64_t)EOperationFlag::Insert 
                | (uint64_t)EOperationFlag::Delete 
                | (uint64_t)EOperationFlag::Duplicate
            );
        }
    }
  

    PropertyNodes.Add(PropertyNode);

    if(Type==EPropertyType::Vector)
    {
        //vector
        const CReflectableVector* VectorBase=reinterpret_cast<const CReflectableVector*>(PropertyNode->Value);
        PropertyNode->SubNodeNum=VectorBase->Num();
        PropertyNode->bIsExpanded=ExendedPropertyValues.Contains(PropertyNode->Value);
        if(! PropertyNode->bIsExpanded)
        {
            return PropertyNode;
        }

        CTVectorGeneralized * VectorType
            = reinterpret_cast<CTVectorGeneralized*>(InType);
        
        CType* ElementType = VectorType->GetElementType().BasicType;
        for (uint64_t i = 0; i < PropertyNode->SubNodeNum; i++)
        {
            auto Item=CreateAndAddPropertyNodeByValue(
                ElementType
                ,VectorBase->At(ElementType,i)
                ,U"["+CString(i) + U"]"
                ,CString(i)
                ,PropertyNode
            );

            //item might be nullptr
            //because not all type is supported now
            if(Item)
            {
                Item->IndexInParent=i;
            }
        }

    }    

    return PropertyNode;
}

REditorReflectedPropertyViewModel::EPropertyType REditorReflectedPropertyViewModel::ToViewType(CType *InType) const
{
    if(InType==CGetType<int64_t>()())
    {
        return EPropertyType::Int64;
    }
    else if(InType==CGetType<float>()())
    {
        return EPropertyType::Float;
    }
    else if(InType==CGetType<CString>()())
    {
        return EPropertyType::String;
    }
    else if(InType==CGetType<bool>()())
    {
        return EPropertyType::Bool;
    }
    else if(InType==WH::TReflectionType<TSharedObjectPtr<RStaticMesh>>::FindOrCreateType())
    {
        return EPropertyType::StaticMesh;
    }
    else if(InType==WH::TReflectionType<TSharedObjectPtr<RMaterial>>::FindOrCreateType())
    {
        return EPropertyType::Material;
    }
    else if(InType->IsVectorType())
    {
        return EPropertyType::Vector;
    }
    else
    {
        return EPropertyType::Invalid;
    }
}
